#!/usr/bin/env python
# Create a new Sage Notebook spkg.
#
# This spkg-dist doesn't need any Python modules of Sage, so it should
# be okay to run it from a system-wide Python (provided it is sufficiently
# recent).  This script *does* need a sage executable to be in the PATH
# because we need to run "sage -pkg" below and also the "sdist" script
# runs "sage -python" and "sage -hg". -- Jeroen Demeyer


import os
import sys
import stat
import shutil
import tarfile
import subprocess
from tempfile import mkdtemp

from pkg_resources import Requirement
from setuptools.package_index import PackageIndex

# Get the version from setup.py.
try:
    version_line = [f for f in open('setup.py').readlines() if 'version' in f][0]
except IndexError:
    sys.stderr.write("Error: Found no version string in 'setup.py'\n")
    sys.exit(1)

i = version_line.find("'")
j = version_line.rfind("'")
if i==-1 or j==-1 or j-i<3:
    sys.stderr.write(
        "Error: Illegal version string in 'setup.py':\n    %s\n" % version_line)
    sys.stderr.write("Perhaps no single quotes used?\n")
    sys.exit(1)
version = version_line[i + 1:j]
print "New SageNB version: %s" % version

# Create the source distribution.
print "Creating the new source tarball..."
sys.stdout.flush()
proc = subprocess.Popen([os.path.join(os.path.curdir, 'sdist')], shell=True)
if proc.wait():
    sys.stderr.write(
        "Error: './sdist' failed. See message(s) above for the specific error.\n")
    sys.exit(1)

# Create the spkg.
base = 'sagenb-%s' % version
path = os.path.join('dist', base)
if os.path.exists(path):
    shutil.rmtree(path)
os.makedirs(path)

file = 'sagenb-%s.tar.gz' % version # created by 'sdist' above
print "Extracting %s..." % file
sys.stdout.flush()
t = tarfile.open(os.path.join('dist', file))
t.extractall(path)
print "Finished extraction."
sys.stdout.flush()

os.chdir(path) # cd dist/sagenb-x.y.z
os.mkdir('src')
print "Moving new source tree..."
sys.stdout.flush()
shutil.move(base, os.path.join('src', 'sagenb')) # mv sagenb-x.y.z src/sagenb

print "Copying 'SPKG.txt'..."
sys.stdout.flush()
shutil.copy(os.path.join(os.path.pardir, os.path.pardir, 'SPKG.txt'),
            os.path.curdir) # cp ../../SPKG.txt . (which is dist/sagenb-x.y.z)

print "Creating 'spkg-install'..."
sys.stdout.flush()
spkg_install = os.path.abspath(os.path.join(os.path.curdir, 'spkg-install'))
spkg_install_fd = open(spkg_install, 'w')


def fetch_packages():
    # This block is here in case we ever need it again.
    # XXX Then also make sure the easy_install commands
    # XXX get written to the correct part of spkg-install!
    # XXX (We currently use a single string for the whole file.)
    print "Fetching the required packages"
    pkg_index = PackageIndex()

    tmp_dir = mkdtemp()

    required_packages = ()

    pkg_locations = []

    for pkg in required_packages:
        print "Fetching %s" % pkg
        dist = pkg_index.fetch_distribution(Requirement.parse(pkg), tmp_dir,
                                            True, True)
        pkg_locations.append(os.path.abspath(dist.location))

    for location in pkg_locations:
        shutil.copy(location, 'src')
        spkg_install_fd.write('easy_install %s\n' % os.path.basename(location))

    return [os.path.basename(location) for location in pkg_locations]


os.chdir(os.path.pardir) # cd .. (now in dist/)

# Write the whole file from a single raw Python string:
# (The #! has to be on the first line of the script.)
spkg_install_fd.write(
r"""#!/usr/bin/env bash

# spkg-install for SageNB, generated by SageNB's spkg-dist

if [ -z "$SAGE_LOCAL" ]; then
    echo >&2 "SAGE_LOCAL undefined - exiting..."
    exit 1
fi

cd src

cd sagenb
python setup.py install
if [ $? -ne 0 ]; then
    echo >&2 "Error running 'setup.py install'."
    exit 1
fi

mkdir -p "$SAGE_ROOT/devel" # Create if it doesn't already exist
if [ $? -ne 0 ]; then
    echo >&2 "Error creating '$SAGE_ROOT/devel'."
    exit 1
fi

echo "Copying SageNB package to '$SAGE_ROOT/devel/sagenb-main'..."

if [ -d "$SAGE_ROOT/devel/sagenb-main" ]; then
    echo "Moving old SageNB package to '$SAGE_ROOT/devel/sagenb-main-old'..."
    rm -rf "$SAGE_ROOT/devel/sagenb-main-old"
    mv "$SAGE_ROOT/devel/sagenb-main" "$SAGE_ROOT/devel/sagenb-main-old"
    if [ $? -ne 0 ]; then
        echo >&2 "Error moving the old 'sagenb-main' branch."
        exit 1
    fi
fi

rm -f "$SAGE_ROOT/devel/sagenb" # Delete just the link itself (if it exists)

cd .. # Back to sagenb-x.y.z/src/
cp -pr sagenb "$SAGE_ROOT/devel/sagenb-main" # Creates new sagenb-main dir
if [ $? -ne 0 ]; then
    echo >&2 "Error copying the new SageNB package."
    exit 1
fi

cd "$SAGE_ROOT/devel"
ln -s sagenb-main sagenb # Create new symbolic link (deleted above)
if [ $? -ne 0 ]; then
    echo >&2 "Error creating symbolic link to '$SAGE_ROOT/devel/sagenb-main'."
    exit 1
fi

# We use relative paths for relocatability.
cd "$SAGE_ROOT/devel/sagenb"
python setup.py develop --egg-path ../../../../devel/sagenb
if [ $? -ne 0 ]; then
    echo >&2 "Error running 'setup.py develop'."
    exit 1
fi

cd "$SAGE_ROOT/local/lib/python/site-packages"
# Use >/dev/null instead of grep -q (which doesn't work on Solaris)
if ! grep sagenb easy-install.pth >/dev/null; then
    # Ugly work-around, we haven't found the real cause yet (see #10176):
    echo "No sagenb path found in 'easy-install.pth'"'!'
    echo "Adding relative sagenb path to 'easy-install.pth'..."
    sed -e '$ i \../../../../devel/sagenb' easy-install.pth > easy-install.pth.$$
    if [ $? -ne 0 ]; then
        echo >&2 "Error adding relative sagenb path to 'easy-install.pth'."
        exit 1
    fi
else
    echo "Making sagenb path in 'easy-install.pth' relative..."
    sed 's/^.*sagenb.*$/..\/..\/..\/..\/devel\/sagenb/' easy-install.pth > easy-install.pth.$$
    if [ $? -ne 0 ]; then
        echo >&2 "Error patching 'easy-install.pth' to have relative path to SageNB."
        exit 1
    fi
fi

# Print paths for debugging
echo "Old path: '`grep sagenb easy-install.pth`'"
echo "New path: '`grep sagenb easy-install.pth.$$`'"

# The following fails only on wrong file permissions etc.:
mv -f easy-install.pth.$$ easy-install.pth
if [ $? -ne 0 ]; then
    echo >&2 "Error overwriting original 'easy-install.pth'."
    exit 1
fi
""")
spkg_install_fd.close()
os.chmod(spkg_install, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP |
         stat.S_IROTH | stat.S_IXOTH) # -rwxr-xr-x

# We are still in dist/, now package sagenb-x.y.z/ :
print "Running 'sage -pkg %s'..."%base
sys.stdout.flush()
if subprocess.call(['sage', '-pkg', base]):
    sys.stderr.write('Error: "sage -pkg %s" failed.\nSee message(s) above for the specific error.\n'%base)
    sys.exit(1)
